/**
 * https://www.tslang.cn/docs/handbook/generics.html
 * Created by Qingger Corp.
 * User: jsspf
 * Date: 2017/11/3
 * Time: 23:55
 */

 
interface GenericIdentityFn<T> {
    (arg:T) : T;
}

interface GenericIdentityFn2 {
    <T>(arg:T) : T;
}

function identity<T>(args:T) : T {
   return args;
}


let myIdentity1 = identity;

// 注意，以下这句话应该这样看 let myIdentity2 : {type} = identity;  type = <T>(arg:T) =>T
// myIdentity2 是一个函数类型。此函数有一个T类型的参数arg,并返回T类型的返回值
let myIdentity2 : <T>(arg:T) => T = identity;

let myIdentity3 = null;
// let myIdentity3 : {<T>(arg:T) : T} = identity;

// 以下这样的写法为什么不妥当？？？？
let myIdentity4 : GenericIdentityFn<number> = identity as GenericIdentityFn<number>;

let myIdentity5 : GenericIdentityFn<number> =  function(arg:number) : number {
    return arg++;
};

let myIdentity6 : GenericIdentityFn2 = identity as GenericIdentityFn2;

console.log(myIdentity1);
console.log(myIdentity2("ss"));
console.log(myIdentity3);




// 泛型约束
interface LengthWise {
    length : number
}
function logginIndentityWithTypeError<T>(arg:T) : T {
    //console.log(arg.length); // error TS2339: Property 'length' does not exist on type 'T'.
    return arg;
}
// 定义一个接口来描述类型的约束条件：T类型是一个含有legnth属性的对象
function logginIndentity<T extends LengthWise>(arg:T) : T {
    console.log(arg.length);  // correct
    return arg;
}
// logginIndentity(3);  // Error
logginIndentity({length:3,value:10}); // Correct


// 泛型中使用类类型
interface ObjectCreateType<T> {
    new() : T
}
function createObject<T>(c:ObjectCreateType<T>) : T {
    return new c();
}

class BeeKeeper {
    hasMask : boolean;
}
class ZooKeeper {
    nametag: string;
}
class Animal {
    numLegs : number
}
class Bee extends Animal {
    keeper : BeeKeeper;
}
class Lion extends Animal {
    keeper : ZooKeeper;
}

function createInstance<A extends Animal>(c:ObjectCreateType<A>) : A{
    return new c();
}

console.log(createInstance(Lion).keeper.nametag); // typechecks!
console.log(createInstance(Bee).keeper.hasMask);  // typeChecks!